#include <stdio.h>
#include <opencv2/opencv.hpp>
#include "opencv_helper.hpp"
#include <time.h>

struct Pad
{
public:
    int top;
    int bottom;
    int left;
    int right;

public:
    Pad(int _top, int _bottom, int _left, int _right):
        top(_top), bottom(_bottom), left(_left), right(_right)
    {
    }
};

namespace och {

// 居中显示文字
void put_text_center(cv::Mat& image, const std::string& text,cv::Point text_center, int fontFace, double fontScale, cv::Scalar fontColor, int thickness = 1)
{
    const int cx = text_center.x;
    const int cy = text_center.y;
    cv::Point org(cx - text.length() * 10, cy + 15); // TODO: remove the hard coded value
    cv::putText(image, text, org, fontFace, fontScale, fontColor, thickness);
}

}

void update(cv::Mat& image, const Pad& pad)
{
    const cv::Scalar white(255, 255, 255);
    const cv::Scalar black(0, 0, 0);

    // clear canvas
    image = white;

    // draw circle
    const int h = image.rows;
    const int w = image.cols;
    cv::Point center(w / 2, h / 2);
    const int radius = (w - pad.left - pad.right) / 2;
    const int thickness = 2;
    cv::circle(image, center, radius, black, thickness);

    cv::Point& O = center;
    cv::Point A(O.x, O.y - radius);

    // draw ticks
    //          A
    //   ..            B
    //              C
    // ..       O       ..
    //
    //   ..          ..
    //          ..
    int fontFace = cv::FONT_HERSHEY_SIMPLEX;
    double fontScale = 1.5;
    for (int i = 1; i <= 12; i++)
    {
        float angle_in_degree = i * (-30);
        float angle_in_rad = och::degree_to_radian(angle_in_degree);
        cv::Point B = och::get_rotated_point(A, center, h, angle_in_rad);
        //cv::circle(image, B, 10, black, -1);

        float len = radius * 0.1;
        
        int cx = (B.x - O.x) * 0.95 + O.x;
        int cy = (B.y - O.y) * 0.95 + O.y;
        cv::Point C(cx, cy);
        cv::line(image, C, B, black, 1);
        
        std::string text = std::to_string(i);

        int dx = (B.x - O.x) * 0.8 + O.x;
        int dy = (B.y - O.y) * 0.8 + O.y;
        cv::Point text_center(dx, dy);
        // cv::Point org(dx - text.length() * 10, dy + 10);
        // cv::putText(image, text, org, fontFace, fontScale, black, thickness);

        och::put_text_center(image, text, text_center, fontFace, fontScale, black, thickness);
    }

    // get current time:  hour, minute, second
    time_t result;

    const char* now_str = asctime(localtime(&result));
    char weekday[10] = {0};
    char month[10] = {0};
    int date;
    int hour;
    int minute;
    int second;
    int year;
    sscanf(now_str, "%s %s %d %d:%d:%d %d", weekday, month, &date, &hour, &minute, &second, &year);

    result = time(NULL);
    // printf("%s%ju secs since the Epoch\n",
    //     asctime(localtime(&result)),
    //         (uintmax_t)result);

    printf("hour=%d, minute=%d, second=%d\n", hour, minute, second);
    float hour_theta = och::degree_to_radian( (hour % 12) * (-30.f));
    cv::Point E = och::get_rotated_point(A, center, h, hour_theta);
    cv::line(image, E, O, black, 6);

    float minute_theta = och::degree_to_radian(minute * (-6.0));
    cv::Point F = och::get_rotated_point(A, center, h, minute_theta);
    cv::line(image, F, O, black, 3);

    float second_theta = och::degree_to_radian(second * (-6.0));
    cv::Point G = och::get_rotated_point(A, center, h, second_theta);
    cv::line(image, G, O, black, 1);
}


int main()
{
    const int w = 500;
    const int h = 500;
    Pad pad(20, 20, 20, 20);
    cv::Size size(w, h);
    cv::Mat image(size, CV_8UC3);

    while (true)
    {
        update(image, pad);
        cv::imshow("tiny clock", image);
        cv::waitKey(200);
    }
    
    return 0;
}

